Recent CTF summary

太久没更博客了,先水一篇,对之前的一些ctf进行一个总结,还有就是对我自己最近给小组出的几道题和我自己ctf中解题脚本的开源,开源地址:https://github.com/The-Itach1/D0g3-ctf-Re

后面就是去继续完成我的远控了,已经完成了大半多了,由于大二事比较多,最近又是考试,就没怎么去管了,后面放假继续弄,应该还要去弄免杀,ctf就基本上不会看了,现在的环境就这样,题目水平也高低不齐,学不到东西了。

最后提一句,大二终于结束了。。。

网刃ctf re

整体都很简单,没什么难度,没想到主办方还发会寄小玩偶,挺可爱。

freestyle

爆破两个数就完事了。

re_easy_func

两个文件,第一个文件是简单的异或。

第二个文件是变表base64。

squid

挺迷惑,这道题也能是re,修改linux时间,定时打开文件即可。

开始还以为是打包成elf的py逆向,然后去查找资料,学到了archive_viewer解包的方法,https://www.jianshu.com/p/3c46eeb32873,没想到,这道题完全不用解包,解出来也没什么可分析的,还以为和国外的一道py打包的calc.exe很像呢。

ez_algorithm

很多字符处理,分析起还是比较痛苦,但是都是单字节,所以完全可以复制ida的代码来爆破,但是需要注意的是得到的答案并不准确,因为里面对一些特殊字符进行了随机处理,替换下即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193

#include<stdio.h>
#include <stdlib.h>
#include <time.h>
//rWto
unsigned char enc[]="BRUF{E6oU9Ci#J9+6nWAhwMR9n:}";
//flag{w3Lc0mE_t0_3NcrYPti0N:}
unsigned __int8 __fastcall encryption3(char a1)
{
unsigned __int8 v2; // [rsp+10h] [rbp+10h]

v2 = a1;
if ( a1 > 64 && a1 <= 70 || a1 > 96 && a1 <= 102 )
return (unsigned __int8)(a1 + 20);
if ( a1 > 84 && a1 <= 90 || a1 > 116 && a1 <= 122 )
return (unsigned __int8)(a1 - 20);
if ( a1 > 71 && a1 <= 77 || a1 > 103 && a1 <= 109 )
return (unsigned __int8)(a1 + 6);
if ( a1 > 77 && a1 <= 83 || a1 > 109 && a1 <= 115 )
return (unsigned __int8)(a1 - 6);
if ( a1 == 71 || a1 == 103 )
return (unsigned __int8)(a1 + 13);
if ( a1 == 84 || a1 == 116 )
return (unsigned __int8)(a1 - 13);
if ( a1 > 47 && a1 <= 57 )
v2 = 105 - a1;
return v2;
}

unsigned __int8 encryption2(char a1)
{
unsigned __int8 v2; // [rsp+30h] [rbp+10h]

v2 = a1;
if ( a1 > 64 && a1 <= 90 )
return (unsigned __int8)encryption3(a1 + 32);
if ( a1 > 96 && a1 <= 122 )
return (unsigned __int8)encryption3(a1 - 32);
if ( a1 > 47 && a1 <= 57 )
v2 = encryption3(a1);
return v2;
}

char encryption()
{
int v1; // eax
char v2; // al
char v3; // al
__int64 v4; // kr00_8
char v5; // al
char v6; // al
int v7; // eax
char v8; // al
char v9; // al
char v10; // al
char v11; // al
char v12; // al
size_t i; // rbx
char v15[1012]; // [rsp+20h] [rbp-60h] BYREF
int v16; // [rsp+414h] [rbp+394h]
int num; // [rsp+42Ch] [rbp+3ACh]
char *flag_i; // [rsp+430h] [rbp+3B0h]
char v21; // [rsp+438h] [rbp+3B8h]

char str1[] = "ckagevdxizblqnwtmsrpufyhoj";
char str2[] = "TMQZWKGOIAGLBYHPCRJSUXEVND";
num = 0;
v16 = 1;
for(i=0;i<28;i++)
{
num=i;
for(char f=0;f<127;f++)
{
flag_i=&f;
if ( *flag_i <= '@' || *flag_i > 'Z' ) // 不是大写字符就进入
{
if ( *flag_i <= '`' || *flag_i > 'z' ) // 不是小写字符就进入
{
if ( *flag_i == '_' )
{
switch ( v16 + rand() % 7 )
{
case 0:
v21 = ':';
break;
case 1:
v21 = '&';
break;
case 2:
v21 = '+';
break;
case 3:
v21 = '*';
break;
case 4:
v21 = '\\';
break;
case 5:
v21 = '?';
break;
case 6:
v21 = '$';
break;
case 7:
v21 = '#';
break;
default:
break;
}
}
else if ( *flag_i <= '/' || *flag_i > '9' )
{
v21 = *flag_i;
}
else
{
v12 = encryption2(*flag_i);
v21 = v12;
}
}
else
{
v7 = num % 4;
if ( num % 4 == 1 )
{
v9 = encryption2(*(unsigned char *)((*flag_i - 97) * (num % 4) + str1));
v21 = v9;
}
else if ( v7 > 1 )
{
if ( v7 == 2 )
{
v10 = encryption2(*(unsigned char *)(((*flag_i - 97) ^ (num % 4)) + str1));
v21 = v10;
}
else if ( v7 == 3 )
{
v11 = encryption2(*(unsigned char *)(*flag_i - 97 + num % 4 + str1));
v21 = v11;
}
}
else if ( !v7 )
{
v8 = encryption2(*(unsigned char *)(*flag_i - 97 - num % 4 + str1));
v21 = v8;
}
}
}
else
{
v1 = num % 4;
if ( num % 4 == 1 )
{
v3 = encryption2(*(unsigned char *)(*flag_i - 65 + num % 4 + str2));
v21 = v3;
}
else if ( v1 > 1 )
{
if ( v1 == 2 )
{
v4 = num * (*flag_i - 65);
v5 = encryption2(*(unsigned char *)(v4+str2));
v21 = v5;
}
else if ( v1 == 3 )
{
v6 = encryption2(*(unsigned char *)(((*flag_i - 65) ^ (num % 4)) + str2));
v21 = v6;
}
}
else if ( !v1 )
{
v2 = encryption2(*(unsigned char *)(*flag_i - 65 - num % 4 + str2));
v21 = v2;
}
}
if(v21==enc[i])
{
printf("%c",f);
break;
}
//printf("%c: %c\n",f,v21);

}


}
}

int main()
{
encryption();
}

2022 Mrctf

这个比赛也是办大了,今年的题和去年的题也不是一个等次了,也就看了一道题,还没做出来。

CICADA

分析了下感觉比较对口,考点也清楚,开始就是解密另一个pe文件,然后内存直接加载运行。

提取出解密后的pe文件发现无法运行,估计做了一些修改吧,也没关系,完全可以在原程序中调试,但是ida分析解密后的pe文件发现代码量很大,一个很丑的vm,里面的数据运算都会经过一个函数。

调试来做,通过打硬件断点来分析关键点,可以分析出开始的逻辑为。

输入为32byte

4字节一组

每一组<<3&0xffffffff ^其本身^i

然后将其还原为32byte

后面就是有很多32byte的数组进行运算,*和+,然后和一个数进行比较,当时没意识到是解方程组,以为数据根本没规律。

基本上后面就是解方程组即可了。

实验班和二次招新道格杯的出题

一共出了5道题,开源在github上,https://github.com/The-Itach1/D0g3-ctf-Re

simple1

简单的异或

simple2

花指令和变表base64.

simple3

自我创建进程反调试,和xxtea。

Crackme

题目难度:中

hint:这个节区名称怎么有点奇怪?

考点:

修改了upx节区名称的upx加壳,mfc,NtQueryInformationProcess反调试,Wincrypt.h库的加密函数

题目地址:https://pan.baidu.com/s/1wHMTcIjpzA9eHbWx_JcZtg 提取码:abcd

wp:

先upx脱壳,将节区名称修改为大写的UPX,然后用upx脱壳,或者采用手脱壳的方式,这里发现,无论哪种方式,脱壳后的exe文件无法运行,所以造成了无法调试的情况,对于Mfc程序来说,这将是比较痛苦的,但是也不是不能分析,熟悉32位upx加壳原理的话,都知道调试到最后的jmp就已经完成了对程序的解密,所以完全可以结合脱壳后的文件,找到关键函数,然后使用原未脱壳的文件进行调试,使用alt+b搜索特征而定位到check函数,然后进行调试。

当然check函数前是有个NtQueryInformationProcess反调试的,这里保留了ntdll这个字符串来方便定位。

加密过程就是10bytekey 5个一组,一组进行md5,一组进行sha1,然后进行验证,验证的密文需要非调试状态才会是正确的。

然后将10byte进行md5加密,作为aes的key。

后面进行对flag进行aes加密。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89

#include <Windows.h>
#include<stdio.h>
bool AesDecrypt(BYTE* pPassword, DWORD dwPasswordLength, BYTE* pData, DWORD& dwDataLength, DWORD dwBufferLength)
{
// TODO: 在此处添加实现代码.
BOOL bRet = TRUE;
HCRYPTPROV hCryptProv = NULL;
HCRYPTHASH hCryptHash = NULL;
HCRYPTKEY hCryptKey = NULL;

do
{
// 获取CSP句柄
bRet = CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT);
if (FALSE == bRet)
{
break;
}

// 创建HASH对象
bRet = CryptCreateHash(hCryptProv, CALG_MD5, NULL, 0, &hCryptHash);
if (FALSE == bRet)
{

break;
}

// 对密钥进行HASH计算
bRet = CryptHashData(hCryptHash, pPassword, dwPasswordLength, 0);
if (FALSE == bRet)
{

break;
}

// 使用HASH来生成密钥
bRet = CryptDeriveKey(hCryptProv, CALG_AES_128, hCryptHash, CRYPT_EXPORTABLE, &hCryptKey);
if (FALSE == bRet)
{

break;
}

// 解密数据
bRet = CryptDecrypt(hCryptKey, NULL, TRUE, 0, pData, &dwDataLength);
if (FALSE == bRet)
{

break;
}

} while (FALSE);

// 关闭释放
if (hCryptKey)
{
CryptDestroyKey(hCryptKey);
}
if (hCryptHash)
{
CryptDestroyHash(hCryptHash);
}
if (hCryptProv)
{
CryptReleaseContext(hCryptProv, 0);
}

return bRet;
return false;
}



int main()
{
BYTE Enc[] = { 0x35,0xf8,0x84,0x29,0x96,0x4f,0x82,0x6b,0x70,0xfe,0x3a,0xff,0x47,0x2f,0x43,0x4b,0x2c,0x68,0xbd,0x16,0x27,0x30,0x82,0x50,0xa9,0x11,0x99,0xf1,0xa0,0x44,0x20,0xc2,0x40,0x18,0x6f,0x5d,0x5b,0xd8,0x4d,0x05,0x44,0x3c,0xb5,0xe7,0x2e,0x87,0x79,0xee };
BYTE Key[] = { 0x44,0x4f,0x8c,0xdc,0xbb,0xb7,0xcb,0x47,0x69,0x3c,0xa9,0x09,0x08,0x70,0xbc,0x40 };

DWORD Enclen = 0x30;
AesDecrypt(Key, 16, Enc, Enclen, MAX_PATH);

for (int i = 0; i < Enclen; i++)
{
printf("%c", Enc[i]);
}

}
//D0g3{H@sh_a^d_Aes_6y_W1nCrypt!!}

这道题我是在给das四月赛出的题在进行了部分修改,看雪上还有一个hook的解法,感觉还不错,原理是钩取了CryptEncrypt,将其变为了CryptDecrypt,然后打印出解密后的字符串。

Keyboard

题目难度:中

hint:注意题目名称,keyboard,keyboard,keyboard,重要的事情说3遍!!!

题目链接:链接:https://pan.baidu.com/s/10oHTA2tr1ztxnsLjHmIojQ  提取码:abcd

题目文本:请将得到的字符串进行32位小写md5加密,然后加上D0g3{}

考点:

假流程,假的加密过程为一个rc4加密,真正的过程是一个线程,里面有键盘钩取,钩取wasd键,进行走迷宫,但有一个tls函数对于迷宫的行列进行了变换,而且对迷宫的一个值进行了修改,里面还有一个汇编写的IsDebugPrevent反调试,也是对列行进行初始化,是错误的引导。迷宫有多条路径,需要写脚本进行走迷宫,得到最短路径。

wp

得到正确的迷宫后,写出脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

#include<stdio.h>
#include<stdlib.h>

char  map[40][40] = {
{0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, },
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 2, }, };

int mark[40][40] = { 0 };
char way[400];
int index = 0;

void check(int x, int y)
{
if (map[x][y] == 2)
{
printf("\nway: %s\n", way);

printf("\n%d", index);
//exit(0);
}
}
void dfs(int x, int y)
{
int xnew = 0, ynew = 0;
check(x, y);//判断走到终点。

xnew = x - 1;
ynew = y;

if (xnew >= 0 && xnew < 40 && ynew >= 0 && ynew < 40 && map[xnew][ynew] != 1 && mark[xnew][ynew] != 1)//不能越界,不能撞墙,不能走以访问路线。
{
way[index++] = 'w';//保存路线,以便输出路线。
mark[x][y] = 1;//标记以访问路线,避免重复访问。
dfs(xnew, ynew);
mark[x][y] = 0;//如果该路不能到达终点,回溯时要将标记还原。
way[--index] = ' ';//路线走不通,还原。
}

xnew = x;
ynew = y + 1;
if (xnew >= 0 && xnew < 40 && ynew >= 0 && ynew < 40 && map[xnew][ynew] != 1 && mark[xnew][ynew] != 1)
{
way[index++] = 'd';
mark[x][y] = 1;
dfs(xnew, ynew);
mark[x][y] = 0;
way[--index] = ' ';
}

xnew = x + 1;
ynew = y;
if (xnew >= 0 && xnew < 40 && ynew >= 0 && ynew < 40 && map[xnew][ynew] != 1 && mark[xnew][ynew] != 1)
{
way[index++] = 's';
mark[x][y] = 1;
dfs(xnew, ynew);
mark[x][y] = 0;
way[--index] = ' ';
}

xnew = x;
ynew = y - 1;
if (xnew >= 0 && xnew < 40 && ynew >= 0 && ynew < 40 && map[xnew][ynew] != 1 && mark[xnew][ynew] != 1)
{
way[index++] = 'a';
mark[x][y] = 1;
dfs(xnew, ynew);
mark[x][y] = 0;
way[--index] = ' ';
}



}
int main()
{
int i, j;

//printf("%d %d \n", map[24][25], map[20][23]);
map[24][25] = 0;
//map[20][23] = 1;
dfs(2, 2);
}

得道最短路径:sdsdddwdddsssssaassdddddddwdddsssddddsssddssssssdsssddsssassdddwwwwwwwddddssdsssdsssssaaasssdsddddwddssssd
然后进行md5加密,套上D0g3{}

由于键盘钩取无法确定字符串的大小写问题,所以默认全部大写,或者默认全部小写。

全部大写的flag:D0g3{1bf4c14e20c7f8559f0c72ad4605c8d5}

全部小写的flag: D0g3{53df848a34fe32ec80b67f8f082928e9}